{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "import random\n",
    "import time\n",
    "from tqdm import tqdm\n",
    "sns.set()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_vocab(file, lower = False):\n",
    "    with open(file, 'r') as fopen:\n",
    "        data = fopen.read()\n",
    "    if lower:\n",
    "        data = data.lower()\n",
    "    vocab = list(set(data))\n",
    "    return data, vocab\n",
    "\n",
    "def embed_to_onehot(data, vocab):\n",
    "    onehot = np.zeros((len(data)), dtype = np.int32)\n",
    "    for i in range(len(data)):\n",
    "        onehot[i] = vocab.index(data[i])\n",
    "    return onehot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "text, text_vocab = get_vocab('shakespeare.txt', lower = False)\n",
    "onehot = embed_to_onehot(text, text_vocab)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "learning_rate = 0.001\n",
    "batch_size = 128\n",
    "sequence_length = 64\n",
    "epoch = 3000\n",
    "num_layers = 2\n",
    "size_layer = 256\n",
    "possible_batch_id = range(len(text) - sequence_length - 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Model:\n",
    "    def __init__(\n",
    "        self, num_layers, size_layer, dimension, sequence_length, learning_rate\n",
    "    ):\n",
    "        def lstm_cell():\n",
    "            return tf.nn.rnn_cell.LSTMCell(\n",
    "                size_layer, sequence_length, state_is_tuple = False\n",
    "            )\n",
    "\n",
    "        self.rnn_cells = tf.nn.rnn_cell.MultiRNNCell(\n",
    "            [lstm_cell() for _ in range(num_layers)], state_is_tuple = False\n",
    "        )\n",
    "        self.X = tf.placeholder(tf.int32, (None, None))\n",
    "        self.Y = tf.placeholder(tf.int32, (None, None))\n",
    "        embeddings = tf.Variable(\n",
    "            tf.random_uniform([len(text_vocab), size_layer], -1, 1)\n",
    "        )\n",
    "        encoder_embedded = tf.nn.embedding_lookup(embeddings, self.X)\n",
    "        self.hidden_layer = tf.placeholder(\n",
    "            tf.float32, (None, num_layers * 2 * size_layer)\n",
    "        )\n",
    "        self.outputs, self.last_state = tf.nn.dynamic_rnn(\n",
    "            self.rnn_cells,\n",
    "            encoder_embedded,\n",
    "            initial_state = self.hidden_layer,\n",
    "            dtype = tf.float32,\n",
    "        )\n",
    "        self.logits = tf.layers.dense(self.outputs, dimension)\n",
    "        logits_long = tf.reshape(self.logits, [-1, dimension])\n",
    "        y_batch_long = tf.reshape(self.Y, [-1])\n",
    "        self.cost = tf.reduce_mean(\n",
    "            tf.nn.sparse_softmax_cross_entropy_with_logits(\n",
    "                logits = logits_long, labels = y_batch_long\n",
    "            )\n",
    "        )\n",
    "        self.optimizer = tf.train.AdamOptimizer(learning_rate).minimize(\n",
    "            self.cost\n",
    "        )\n",
    "        self.correct_pred = tf.equal(\n",
    "            tf.argmax(logits_long, 1), tf.cast(y_batch_long, tf.int64)\n",
    "        )\n",
    "        self.accuracy = tf.reduce_mean(tf.cast(self.correct_pred, tf.float32))\n",
    "        self.final_outputs = tf.nn.softmax(self.logits)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:<tensorflow.python.ops.rnn_cell_impl.LSTMCell object at 0x7fa18ec2ada0>: Using a concatenated state is slower and will soon be deprecated.  Use state_is_tuple=True.\n",
      "WARNING:tensorflow:<tensorflow.python.ops.rnn_cell_impl.LSTMCell object at 0x7fa18ec2a588>: Using a concatenated state is slower and will soon be deprecated.  Use state_is_tuple=True.\n"
     ]
    }
   ],
   "source": [
    "tf.reset_default_graph()\n",
    "sess = tf.InteractiveSession()\n",
    "model = Model(num_layers, size_layer, len(text_vocab), sequence_length, learning_rate)\n",
    "sess.run(tf.global_variables_initializer())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "common\n"
     ]
    }
   ],
   "source": [
    "split_text = text.split()\n",
    "tag = split_text[np.random.randint(0, len(split_text))]\n",
    "print(tag)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_random_batch():\n",
    "    LOST, ACCURACY = [], []\n",
    "    pbar = tqdm(range(epoch), desc = 'epoch')\n",
    "    for i in pbar:\n",
    "        last_time = time.time()\n",
    "        init_value = np.zeros((batch_size, num_layers * 2 * size_layer))\n",
    "        batch_x = np.zeros((batch_size, sequence_length))\n",
    "        batch_y = np.zeros((batch_size, sequence_length))\n",
    "        batch_id = random.sample(possible_batch_id, batch_size)\n",
    "        for k in range(batch_size):\n",
    "            batch_x[k] = embed_to_onehot(text[batch_id[k]:batch_id[k]+sequence_length],text_vocab)\n",
    "            batch_y[k] = embed_to_onehot(text[batch_id[k]+1:batch_id[k]+sequence_length+1],text_vocab)\n",
    "        last_state, _, loss = sess.run([model.last_state, model.optimizer, model.cost], \n",
    "                                       feed_dict = {model.X: batch_x, \n",
    "                                                    model.Y: batch_y,\n",
    "                                                    model.hidden_layer: init_value})\n",
    "        accuracy = sess.run(model.accuracy, feed_dict = {model.X: batch_x, \n",
    "                                                         model.Y: batch_y, \n",
    "                                                         model.hidden_layer: init_value})\n",
    "        ACCURACY.append(accuracy); LOST.append(loss)\n",
    "        init_value = last_state\n",
    "        pbar.set_postfix(cost = loss, accuracy = accuracy)\n",
    "    return LOST, ACCURACY"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_random_sequence():\n",
    "    LOST, ACCURACY = [], []\n",
    "    pbar = tqdm(range(epoch), desc = 'epoch')\n",
    "    for i in pbar:\n",
    "        last_time = time.time()\n",
    "        init_value = np.zeros((batch_size, num_layers * 2 * size_layer))\n",
    "        batch_x = np.zeros((batch_size, sequence_length))\n",
    "        batch_y = np.zeros((batch_size, sequence_length))\n",
    "        batch_id = random.sample(possible_batch_id, batch_size)\n",
    "        for n in range(sequence_length):\n",
    "            id1 = [k + n for k in batch_id]\n",
    "            id2 = [k + n + 1 for k in batch_id]\n",
    "            batch_x[:,n] = onehot[id1]\n",
    "            batch_y[:,n] = onehot[id2]\n",
    "        last_state, _, loss = sess.run([model.last_state, model.optimizer, model.cost], \n",
    "                                       feed_dict = {model.X: batch_x, \n",
    "                                                    model.Y: batch_y,\n",
    "                                                    model.hidden_layer: init_value})\n",
    "        accuracy = sess.run(model.accuracy, feed_dict = {model.X: batch_x, \n",
    "                                                         model.Y: batch_y, \n",
    "                                                         model.hidden_layer: init_value})\n",
    "        ACCURACY.append(accuracy); LOST.append(loss)\n",
    "        init_value = last_state\n",
    "        pbar.set_postfix(cost = loss, accuracy = accuracy)\n",
    "    return LOST, ACCURACY"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "epoch: 100%|██████████| 3000/3000 [06:31<00:00,  7.66it/s, accuracy=0.611, cost=1.26]\n"
     ]
    }
   ],
   "source": [
    "LOST, ACCURACY = train_random_sequence()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize = (15, 5))\n",
    "plt.subplot(1, 2, 1)\n",
    "EPOCH = np.arange(len(LOST))\n",
    "plt.plot(EPOCH, LOST)\n",
    "plt.xlabel('epoch')\n",
    "plt.ylabel('loss')\n",
    "plt.subplot(1, 2, 2)\n",
    "plt.plot(EPOCH, ACCURACY)\n",
    "plt.xlabel('epoch')\n",
    "plt.ylabel('accuracy')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def generate_based_sequence(length_sentence, argmax = False):\n",
    "    sentence_generated = tag\n",
    "    onehot = embed_to_onehot(tag, text_vocab)\n",
    "    init_value = np.zeros((1, num_layers * 2 * size_layer))\n",
    "    for i in range(len(tag)):\n",
    "        batch_x = np.zeros((1, 1))\n",
    "        batch_x[0] = onehot[i]\n",
    "        last_state, prob = sess.run(\n",
    "            [model.last_state, model.final_outputs],\n",
    "            feed_dict = {model.X: batch_x, model.hidden_layer: init_value},\n",
    "        )\n",
    "        init_value = last_state\n",
    "\n",
    "    for i in range(length_sentence):\n",
    "        if argmax:\n",
    "            char = np.argmax(prob[0][0])\n",
    "        else:\n",
    "            char = np.random.choice(range(len(text_vocab)), p = prob[0][0])\n",
    "        element = text_vocab[char]\n",
    "        sentence_generated += element\n",
    "        onehot = embed_to_onehot(element, text_vocab)\n",
    "        batch_x = np.zeros((1, 1))\n",
    "        batch_x[0] = onehot[0]\n",
    "        last_state, prob = sess.run(\n",
    "            [model.last_state, model.final_outputs],\n",
    "            feed_dict = {model.X: batch_x, model.hidden_layer: init_value},\n",
    "        )\n",
    "        init_value = last_state\n",
    "\n",
    "    return sentence_generated"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "common boots: yet let him king about\n",
      "Lends and coutse against home of.\n",
      "\n",
      "TRUTISA:\n",
      "Are royal sea from this wine feel'd by himself.\n",
      "\n",
      "YORK:\n",
      "Secore thou hast said 'Redian so were hunter sun?\n",
      "\n",
      "KATHARINA:\n",
      "Good married! his compovers' insul.\n",
      "\n",
      "CORIOLANUS:\n",
      "Should say your son must, not that is gone possess:\n",
      "withtering wandering villains therefore,\n",
      "Because there discreeply, Tylanks and the\n",
      "wight of lossans, Isabel, not the other sits, was by\n",
      "This seasing sleep back to helps it.\n",
      "But for, my lord on my poor loathsomety,\n",
      "But like his bed: I do a trade?\n",
      "Heaven knows your worship or faith, but\n",
      "I' my son, to take it stirn; easy one sore\n",
      "The people or his womper. In it thou shalt\n",
      "besire your studiates thus all four soul that cares\n",
      "Nothing being mercing tomborn protecticle?\n",
      "Our lessings these stames their returns:\n",
      "To remain that e'er you know what told me?\n",
      "Fie, sirrah, I kill thee woman, forget to do;\n",
      "Jook our life winged and ageness will perfect\n",
      "Is by their eight; he though you are briever.\n",
      "Go. But, if the pa\n"
     ]
    }
   ],
   "source": [
    "print(generate_based_sequence(1000,True))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "common from the crown,\n",
      "I mean me not, but one yet admit of this meet!\n",
      "\n",
      "CORIOLANUS:\n",
      "Not to London get him within the people\n",
      "Of entertain, has not in post straight.\n",
      "\n",
      "DUKE OF YORK:\n",
      "How fie the orace of Exeter; will not\n",
      "To know you to frop both a heavier true.\n",
      "\n",
      "JULIET:\n",
      "What have you march. Romeo my corse?\n",
      "What is the queen the world is miss for this,\n",
      "Fight it wold beholding contents.\n",
      "\n",
      "CAMILLO:\n",
      "Why\n",
      "so do?\n",
      "\n",
      "BRUTUS:\n",
      "Yet a man quite unesty woached pride?\n",
      "Doth you bace, his worthy as word out: now\n",
      "I will bring the hatrest sea, and for me anon\n",
      "My powers, so hinder like that back to teach:\n",
      "For honest straight, the sight of this house\n",
      "And swares me with praise a daggers: itsell'd;\n",
      "For well straight their birdestments, then abstatter:\n",
      "If which world they see him says, and we should to\n",
      "sulmot's chasbe, seath coming the reasons of my kind,\n",
      "I kneel the wonderers' a man\n",
      "Affection, we him convey harmoofs,\n",
      "Pity Clarence will he not much odd;\n",
      "Must come hither.\n",
      "\n",
      "COMINIUS Xague:\n",
      "I tribunes shall eat weet wonder w\n"
     ]
    }
   ],
   "source": [
    "print(generate_based_sequence(1000,False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
